#include "datamodel.h"
#include "protocol.h"

#include <QByteArray>
#include <array>

DataModel::DataModel(QObject *parent) :
    QAbstractTableModel(parent)
{
    init();
}

void DataModel::setData(const QByteArray &array)
{
    beginResetModel();
    this->array = array;
    endResetModel();
}

qint8 DataModel::getQint8(const QByteArray &array) const
{
    QDataStream in1(array);
    in1.setByteOrder(byteOrder);
    qint8 n1;
    in1 >> n1;

    return n1;
}

quint8 DataModel::getQuint8(const QByteArray &array) const
{
    QDataStream in2(array);
    in2.setByteOrder(byteOrder);
    quint8 nu1;
    in2 >> nu1;

    return nu1;
}

qint16 DataModel::getQint16(const QByteArray &array) const
{
    QDataStream in3(array);
    in3.setByteOrder(byteOrder);
    qint16 n2;
    in3 >> n2;

    return n2;
}

quint16 DataModel::getQuint16(const QByteArray &array) const
{
    QDataStream in4(array);
    in4.setByteOrder(byteOrder);
    quint16 nu2;
    in4 >> nu2;

    return nu2;
}

qint32 DataModel::getQint32(const QByteArray &array) const
{
    QByteArray A_array = fillData();
    QDataStream *in5;
    if(array.size()==3){
        in5 = new QDataStream(A_array);
    }else{
        in5 = new QDataStream(array);
    }
    in5->setByteOrder(byteOrder);
    qint32 n4;
    *in5 >> n4;

    return n4;
}

quint32 DataModel::getQuint32(const QByteArray &array) const
{
    QByteArray A_array = fillData();
    QDataStream *in6;
    if(array.size()==3){
        in6 = new QDataStream(A_array);
    }else{
        in6 = new QDataStream(array);
    }
    in6->setByteOrder(byteOrder);
    quint32 nu4;
    *in6 >> nu4;

    return nu4;
}

qint64 DataModel::getQint64(const QByteArray &array) const
{
    QByteArray A_array = fillData();
    QDataStream *in7;
    if(array.size() > 4 && array.size() < 8){
        in7 = new QDataStream(A_array);
    }else{
        in7 = new QDataStream(array);
    }
    in7->setByteOrder(byteOrder);
    qint64 n8;
    *in7 >> n8;

    return n8;
}

quint64 DataModel::getQuint64(const QByteArray &array) const
{
    QByteArray A_array = fillData();
    QDataStream *in8;
    if(array.size() > 4 && array.size() < 8){
        in8 = new QDataStream(A_array);
    }else{
        in8 = new QDataStream(array);
    }
    in8->setByteOrder(byteOrder);
    quint64 nu8;
    *in8 >> nu8;

    return nu8;
}

void DataModel::littleEndian(bool checked)
{
    beginResetModel();
    byteOrder = checked ? QDataStream::LittleEndian : QDataStream::BigEndian;
    endResetModel();
}

void DataModel::init()
{
    types.append(tr("Bin8"));
    types.append(tr("Int8"));
    types.append(tr("UInt8"));
    types.append(tr("Int16"));
    types.append(tr("UInt16"));
    types.append(tr("Int32"));
    types.append(tr("UInt32"));
    types.append(tr("Int64"));
    types.append(tr("UInt64"));
    types.append(tr("JD"));
    types.append(tr("JS"));
    types.append(tr("ERT"));
    types.append(tr("BID"));
}

int DataModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return types.count();
}

int DataModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 2;
}

QVariant DataModel::data(const QModelIndex &index, int role) const
{
    if (role == Qt::DisplayRole) {
        int row = index.row();
        int column = index.column();
        if (column == 0) {
            return types.at(row);
        } else {
            QDataStream in(array);
            in.setByteOrder(byteOrder);
            if (row == 0 && array.size() >= 1) {
                return QString("%1").arg((unsigned char)array.at(0), 8, 2, QChar('0'));
            } else if (row == 1 && array.size() >= 1) {
                qint8 n;
                in >> n;
                return QString("%1").arg(n);
            } else if (row == 2 && array.size() >= 1) {
                quint8 n;
                in >> n;
                return QString("%1").arg(n);
            } else if (row == 3 && array.size() >= 1) {
                return tranqint16(array);
            } else if (row == 4 && array.size() >= 1) {
               return tranquint16(array);
            } else if (row == 5 && array.size() >= 1) {
                return tranqint32(array);
            } else if (row == 6 && array.size() >= 1) {
               return tranquint32(array);
            } else if (row == 7 && array.size() >= 1) {
               return tranqint64(array);
            } else if (row == 8 && array.size() >= 1) {
               return tranquint64(array);
            } else if (row == 9 && array.size() >= 2) {
                quint16 jd;
                in >> jd;
                return jdString(jd);
            } else if (row == 10 && array.size() >= 4) {
                quint32 js;
                in >> js;
                return jsString(js);
            }else if (row == 11 && array.size() >= 6) {
                quint32 js;
                in >> js;
                quint16 ms;
                in >> ms;
                return ertString(js,ms);
            }else if (row == 12 && array.size() >= 4) {
                quint32 bid;
                in >> bid;
                return bidString(bid);
            }
        }
    }

    return QVariant();
}

QByteArray DataModel::fillData() const
{
    QByteArray A_array ;
    if(array.size() == 3){
        uchar d[] = {0x00,0x00,0x00,0x00};
        QByteArray dat((char*)d,4);
        A_array=dat;
        if(byteOrder == QDataStream::LittleEndian){
            A_array.replace(0,3,array);
        }else{
            A_array.replace(1,3,array);
        }
    }
    if(array.size() > 3 && array.size() < 8){
        uchar d[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
        QByteArray dat((char*)d,8);
        A_array=dat;
        if(byteOrder == QDataStream::LittleEndian){
            A_array.replace(0,array.size(),array);
        }else{
            A_array.replace(8-array.size(),array.size(),array);
        }
    }
    return A_array;
}

QString DataModel::tranqint16(const QByteArray &array) const
{
    if(array.size() == 1){
        return QString("%1").arg(getQint8(array));
    }else{
        return QString("%1").arg(getQint16(array));
    }
}

QString DataModel::tranquint16(const QByteArray &array) const
{
    if(array.size() == 1){
        return QString("%1").arg(getQuint8(array));
    }else{
        return QString("%1").arg(getQuint16(array));
    }
}

QString DataModel::tranqint32(const QByteArray &array) const
{
    if(array.size() ==1){
        return QString("%1").arg(getQint8(array));
    }else if(array.size() >1 && array.size() <3){
        return QString("%1").arg(getQint16(array));
    }else{
        return QString("%1").arg(getQint32(array));
    }
}

QString DataModel::tranquint32(const QByteArray &array) const
{
    if(array.size() ==1){
        return QString("%1").arg(getQuint8(array));
    }else if(array.size() >1 && array.size() <3){
        return QString("%1").arg(getQuint16(array));
    }else{
        return QString("%1").arg(getQuint32(array));
    }
}

QString DataModel::tranqint64(const QByteArray &array) const
{
    if(array.size() ==1){
        return QString("%1").arg(getQint8(array));
    }else if(array.size() >1 && array.size() <3){
        return QString("%1").arg(getQint16(array));
    }else if(array.size() >= 3 && array.size() < 5){
        return QString("%1").arg(getQint32(array));
    }else{
        return QString("%1").arg(getQint64(array));
    }
}

QString DataModel::tranquint64(const QByteArray &array) const
{
    if(array.size() ==1){
        return QString("%1").arg(getQuint8(array));
    }else if(array.size() >1 && array.size() <3){
        return QString("%1").arg(getQuint16(array));
    }else if(array.size() >= 3 && array.size() < 5){
        return QString("%1").arg(getQuint32(array));
    }else{
        return QString("%1").arg(getQuint64(array));
    }
}
